<h1 id="布局管理">布局管理</h1>
<p>在一个GUI程序里，布局是一个很重要的方面。布局就是如何管理应用中的元素和窗口。有两种方式可以搞定：绝对定位和PyQt5的layout类</p>
<h2 id="绝对定位">绝对定位</h2>
<p>每个程序都是以像素为单位区分元素的位置，衡量元素的大小。所以我们完全可以使用绝对定位搞定每个元素和窗口的位置。但是这也有局限性：</p>
<ul>
<li>元素不会随着我们更改窗口的位置和大小而变化。</li>
<li>不能适用于不同的平台和不同分辨率的显示器</li>
<li>更改应用字体大小会破坏布局</li>
<li>如果我们决定重构这个应用，需要全部计算一下每个元素的位置和大小</li>
</ul>
<p>下面这个就是绝对定位的应用</p>
<div class="sourceCode" id="cb1"><pre><code class="language-python"><a class="sourceLine" id="cb1-1" data-line-number="1"><span class="co">#!/usr/bin/python3</span></a>
<a class="sourceLine" id="cb1-2" data-line-number="2"><span class="co"># -*- coding: utf-8 -*-</span></a>
<a class="sourceLine" id="cb1-3" data-line-number="3"></a>
<a class="sourceLine" id="cb1-4" data-line-number="4"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb1-5" data-line-number="5"><span class="co">ZetCode PyQt5 tutorial </span></a>
<a class="sourceLine" id="cb1-6" data-line-number="6"></a>
<a class="sourceLine" id="cb1-7" data-line-number="7"><span class="co">This example shows three labels on a window</span></a>
<a class="sourceLine" id="cb1-8" data-line-number="8"><span class="co">using absolute positioning. </span></a>
<a class="sourceLine" id="cb1-9" data-line-number="9"></a>
<a class="sourceLine" id="cb1-10" data-line-number="10"><span class="co">Author: Jan Bodnar</span></a>
<a class="sourceLine" id="cb1-11" data-line-number="11"><span class="co">Website: zetcode.com </span></a>
<a class="sourceLine" id="cb1-12" data-line-number="12"><span class="co">Last edited: August 2017</span></a>
<a class="sourceLine" id="cb1-13" data-line-number="13"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb1-14" data-line-number="14"></a>
<a class="sourceLine" id="cb1-15" data-line-number="15"><span class="im">import</span> sys</a>
<a class="sourceLine" id="cb1-16" data-line-number="16"><span class="im">from</span> PyQt5.QtWidgets <span class="im">import</span> QWidget, QLabel, QApplication</a>
<a class="sourceLine" id="cb1-17" data-line-number="17"></a>
<a class="sourceLine" id="cb1-18" data-line-number="18"><span class="kw">class</span> Example(QWidget):</a>
<a class="sourceLine" id="cb1-19" data-line-number="19"></a>
<a class="sourceLine" id="cb1-20" data-line-number="20">    <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>):</a>
<a class="sourceLine" id="cb1-21" data-line-number="21">        <span class="bu">super</span>().<span class="fu">__init__</span>()</a>
<a class="sourceLine" id="cb1-22" data-line-number="22"></a>
<a class="sourceLine" id="cb1-23" data-line-number="23">        <span class="va">self</span>.initUI()</a>
<a class="sourceLine" id="cb1-24" data-line-number="24"></a>
<a class="sourceLine" id="cb1-25" data-line-number="25"></a>
<a class="sourceLine" id="cb1-26" data-line-number="26">    <span class="kw">def</span> initUI(<span class="va">self</span>):</a>
<a class="sourceLine" id="cb1-27" data-line-number="27"></a>
<a class="sourceLine" id="cb1-28" data-line-number="28">        lbl1 <span class="op">=</span> QLabel(<span class="st">&#39;Zetcode&#39;</span>, <span class="va">self</span>)</a>
<a class="sourceLine" id="cb1-29" data-line-number="29">        lbl1.move(<span class="dv">15</span>, <span class="dv">10</span>)</a>
<a class="sourceLine" id="cb1-30" data-line-number="30"></a>
<a class="sourceLine" id="cb1-31" data-line-number="31">        lbl2 <span class="op">=</span> QLabel(<span class="st">&#39;tutorials&#39;</span>, <span class="va">self</span>)</a>
<a class="sourceLine" id="cb1-32" data-line-number="32">        lbl2.move(<span class="dv">35</span>, <span class="dv">40</span>)</a>
<a class="sourceLine" id="cb1-33" data-line-number="33"></a>
<a class="sourceLine" id="cb1-34" data-line-number="34">        lbl3 <span class="op">=</span> QLabel(<span class="st">&#39;for programmers&#39;</span>, <span class="va">self</span>)</a>
<a class="sourceLine" id="cb1-35" data-line-number="35">        lbl3.move(<span class="dv">55</span>, <span class="dv">70</span>)        </a>
<a class="sourceLine" id="cb1-36" data-line-number="36"></a>
<a class="sourceLine" id="cb1-37" data-line-number="37">        <span class="va">self</span>.setGeometry(<span class="dv">300</span>, <span class="dv">300</span>, <span class="dv">250</span>, <span class="dv">150</span>)</a>
<a class="sourceLine" id="cb1-38" data-line-number="38">        <span class="va">self</span>.setWindowTitle(<span class="st">&#39;Absolute&#39;</span>)    </a>
<a class="sourceLine" id="cb1-39" data-line-number="39">        <span class="va">self</span>.show()</a>
<a class="sourceLine" id="cb1-40" data-line-number="40"></a>
<a class="sourceLine" id="cb1-41" data-line-number="41"></a>
<a class="sourceLine" id="cb1-42" data-line-number="42"><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</a>
<a class="sourceLine" id="cb1-43" data-line-number="43"></a>
<a class="sourceLine" id="cb1-44" data-line-number="44">    app <span class="op">=</span> QApplication(sys.argv)</a>
<a class="sourceLine" id="cb1-45" data-line-number="45">    ex <span class="op">=</span> Example()</a>
<a class="sourceLine" id="cb1-46" data-line-number="46">    sys.exit(app.exec_())</a></code></pre></div>
<p>我们使用move()方法定位了每一个元素，使用x、y坐标。x、y坐标的原点是程序的左上角。</p>
<pre><code class="language-python">lbl1 = QLabel(&#39;Zetcode&#39;, self)
lbl1.move(15, 10)</code></pre>
<p>这个元素的左上角就在这个程序的左上角开始的(15, 10)的位置。</p>
<p>程序展示：</p>
<figure>
<img class="whitelist" src="docs/PyQt5/images/3-absolute.png" alt="Absolute positioning" />
</figure>
<h2 id="盒布局">盒布局</h2>
<p>使用盒布局能让程序具有更强的适应性。这个才是布局一个应用的更合适的方式。<code>QHBoxLayout</code>和<code>QVBoxLayout</code>是基本的布局类，分别是水平布局和垂直布局。</p>
<p>如果我们需要把两个按钮放在程序的右下角，创建这样的布局，我们只需要一个水平布局加一个垂直布局的盒子就可以了。再用弹性布局增加一点间隙。</p>
<div class="sourceCode" id="cb3"><pre><code class="language-python"><a class="sourceLine" id="cb3-1" data-line-number="1"><span class="co">#!/usr/bin/python3</span></a>
<a class="sourceLine" id="cb3-2" data-line-number="2"><span class="co"># -*- coding: utf-8 -*-</span></a>
<a class="sourceLine" id="cb3-3" data-line-number="3"></a>
<a class="sourceLine" id="cb3-4" data-line-number="4"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb3-5" data-line-number="5"><span class="co">ZetCode PyQt5 tutorial </span></a>
<a class="sourceLine" id="cb3-6" data-line-number="6"></a>
<a class="sourceLine" id="cb3-7" data-line-number="7"><span class="co">In this example, we position two push</span></a>
<a class="sourceLine" id="cb3-8" data-line-number="8"><span class="co">buttons in the bottom-right corner </span></a>
<a class="sourceLine" id="cb3-9" data-line-number="9"><span class="co">of the window. </span></a>
<a class="sourceLine" id="cb3-10" data-line-number="10"></a>
<a class="sourceLine" id="cb3-11" data-line-number="11"><span class="co">Author: Jan Bodnar</span></a>
<a class="sourceLine" id="cb3-12" data-line-number="12"><span class="co">Website: zetcode.com </span></a>
<a class="sourceLine" id="cb3-13" data-line-number="13"><span class="co">Last edited: August 2017</span></a>
<a class="sourceLine" id="cb3-14" data-line-number="14"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb3-15" data-line-number="15"></a>
<a class="sourceLine" id="cb3-16" data-line-number="16"><span class="im">import</span> sys</a>
<a class="sourceLine" id="cb3-17" data-line-number="17"><span class="im">from</span> PyQt5.QtWidgets <span class="im">import</span> (QWidget, QPushButton, </a>
<a class="sourceLine" id="cb3-18" data-line-number="18">    QHBoxLayout, QVBoxLayout, QApplication)</a>
<a class="sourceLine" id="cb3-19" data-line-number="19"></a>
<a class="sourceLine" id="cb3-20" data-line-number="20"></a>
<a class="sourceLine" id="cb3-21" data-line-number="21"><span class="kw">class</span> Example(QWidget):</a>
<a class="sourceLine" id="cb3-22" data-line-number="22"></a>
<a class="sourceLine" id="cb3-23" data-line-number="23">    <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>):</a>
<a class="sourceLine" id="cb3-24" data-line-number="24">        <span class="bu">super</span>().<span class="fu">__init__</span>()</a>
<a class="sourceLine" id="cb3-25" data-line-number="25"></a>
<a class="sourceLine" id="cb3-26" data-line-number="26">        <span class="va">self</span>.initUI()</a>
<a class="sourceLine" id="cb3-27" data-line-number="27"></a>
<a class="sourceLine" id="cb3-28" data-line-number="28"></a>
<a class="sourceLine" id="cb3-29" data-line-number="29">    <span class="kw">def</span> initUI(<span class="va">self</span>):</a>
<a class="sourceLine" id="cb3-30" data-line-number="30"></a>
<a class="sourceLine" id="cb3-31" data-line-number="31">        okButton <span class="op">=</span> QPushButton(<span class="st">&quot;OK&quot;</span>)</a>
<a class="sourceLine" id="cb3-32" data-line-number="32">        cancelButton <span class="op">=</span> QPushButton(<span class="st">&quot;Cancel&quot;</span>)</a>
<a class="sourceLine" id="cb3-33" data-line-number="33"></a>
<a class="sourceLine" id="cb3-34" data-line-number="34">        hbox <span class="op">=</span> QHBoxLayout()</a>
<a class="sourceLine" id="cb3-35" data-line-number="35">        hbox.addStretch(<span class="dv">1</span>)</a>
<a class="sourceLine" id="cb3-36" data-line-number="36">        hbox.addWidget(okButton)</a>
<a class="sourceLine" id="cb3-37" data-line-number="37">        hbox.addWidget(cancelButton)</a>
<a class="sourceLine" id="cb3-38" data-line-number="38"></a>
<a class="sourceLine" id="cb3-39" data-line-number="39">        vbox <span class="op">=</span> QVBoxLayout()</a>
<a class="sourceLine" id="cb3-40" data-line-number="40">        vbox.addStretch(<span class="dv">1</span>)</a>
<a class="sourceLine" id="cb3-41" data-line-number="41">        vbox.addLayout(hbox)</a>
<a class="sourceLine" id="cb3-42" data-line-number="42"></a>
<a class="sourceLine" id="cb3-43" data-line-number="43">        <span class="va">self</span>.setLayout(vbox)    </a>
<a class="sourceLine" id="cb3-44" data-line-number="44"></a>
<a class="sourceLine" id="cb3-45" data-line-number="45">        <span class="va">self</span>.setGeometry(<span class="dv">300</span>, <span class="dv">300</span>, <span class="dv">300</span>, <span class="dv">150</span>)</a>
<a class="sourceLine" id="cb3-46" data-line-number="46">        <span class="va">self</span>.setWindowTitle(<span class="st">&#39;Buttons&#39;</span>)    </a>
<a class="sourceLine" id="cb3-47" data-line-number="47">        <span class="va">self</span>.show()</a>
<a class="sourceLine" id="cb3-48" data-line-number="48"></a>
<a class="sourceLine" id="cb3-49" data-line-number="49"></a>
<a class="sourceLine" id="cb3-50" data-line-number="50"><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</a>
<a class="sourceLine" id="cb3-51" data-line-number="51"></a>
<a class="sourceLine" id="cb3-52" data-line-number="52">    app <span class="op">=</span> QApplication(sys.argv)</a>
<a class="sourceLine" id="cb3-53" data-line-number="53">    ex <span class="op">=</span> Example()</a>
<a class="sourceLine" id="cb3-54" data-line-number="54">    sys.exit(app.exec_())</a></code></pre></div>
<p>上面的例子完成了在应用的右下角放了两个按钮的需求。当改变窗口大小的时候，它们能依然保持在相对的位置。我们同时使用了<code>QHBoxLayout</code>和<code>QVBoxLayout</code>。</p>
<pre><code class="language-python">okButton = QPushButton(&quot;OK&quot;)
cancelButton = QPushButton(&quot;Cancel&quot;)</code></pre>
<p>这是创建了两个按钮。</p>
<pre><code class="language-python">hbox = QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(okButton)
hbox.addWidget(cancelButton)</code></pre>
<p>创建一个水平布局，增加两个按钮和弹性空间。stretch函数在两个按钮前面增加了一些弹性空间。下一步我们把这些元素放在应用的右下角。</p>
<pre><code class="language-python">vbox = QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)</code></pre>
<p>为了布局需要，我们把这个水平布局放到了一个垂直布局盒里面。弹性元素会把所有的元素一起都放置在应用的右下角。</p>
<pre><code class="language-python">self.setLayout(vbox)</code></pre>
<p>最后，我们就得到了我们想要的布局。</p>
<p>程序预览：</p>
<figure>
<img class="whitelist" src="docs/PyQt5/images/3-buttons.png" alt="buttons" />
</figure>
<h2 id="栅格布局">栅格布局</h2>
<p>最常用的还是栅格布局了。这种布局是把窗口分为行和列。创建和使用栅格布局，需要使用QGridLayout模块。</p>
<div class="sourceCode" id="cb8"><pre><code class="language-python"><a class="sourceLine" id="cb8-1" data-line-number="1"><span class="co">#!/usr/bin/python3</span></a>
<a class="sourceLine" id="cb8-2" data-line-number="2"><span class="co"># -*- coding: utf-8 -*-</span></a>
<a class="sourceLine" id="cb8-3" data-line-number="3"></a>
<a class="sourceLine" id="cb8-4" data-line-number="4"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb8-5" data-line-number="5"><span class="co">ZetCode PyQt5 tutorial </span></a>
<a class="sourceLine" id="cb8-6" data-line-number="6"></a>
<a class="sourceLine" id="cb8-7" data-line-number="7"><span class="co">In this example, we create a skeleton</span></a>
<a class="sourceLine" id="cb8-8" data-line-number="8"><span class="co">of a calculator using a QGridLayout.</span></a>
<a class="sourceLine" id="cb8-9" data-line-number="9"></a>
<a class="sourceLine" id="cb8-10" data-line-number="10"><span class="co">author: Jan Bodnar</span></a>
<a class="sourceLine" id="cb8-11" data-line-number="11"><span class="co">website: zetcode.com </span></a>
<a class="sourceLine" id="cb8-12" data-line-number="12"><span class="co">last edited: January 2015</span></a>
<a class="sourceLine" id="cb8-13" data-line-number="13"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb8-14" data-line-number="14"></a>
<a class="sourceLine" id="cb8-15" data-line-number="15"><span class="im">import</span> sys</a>
<a class="sourceLine" id="cb8-16" data-line-number="16"><span class="im">from</span> PyQt5.QtWidgets <span class="im">import</span> (QWidget, QGridLayout, </a>
<a class="sourceLine" id="cb8-17" data-line-number="17">    QPushButton, QApplication)</a>
<a class="sourceLine" id="cb8-18" data-line-number="18"></a>
<a class="sourceLine" id="cb8-19" data-line-number="19"></a>
<a class="sourceLine" id="cb8-20" data-line-number="20"><span class="kw">class</span> Example(QWidget):</a>
<a class="sourceLine" id="cb8-21" data-line-number="21"></a>
<a class="sourceLine" id="cb8-22" data-line-number="22">    <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>):</a>
<a class="sourceLine" id="cb8-23" data-line-number="23">        <span class="bu">super</span>().<span class="fu">__init__</span>()</a>
<a class="sourceLine" id="cb8-24" data-line-number="24"></a>
<a class="sourceLine" id="cb8-25" data-line-number="25">        <span class="va">self</span>.initUI()</a>
<a class="sourceLine" id="cb8-26" data-line-number="26"></a>
<a class="sourceLine" id="cb8-27" data-line-number="27"></a>
<a class="sourceLine" id="cb8-28" data-line-number="28">    <span class="kw">def</span> initUI(<span class="va">self</span>):</a>
<a class="sourceLine" id="cb8-29" data-line-number="29"></a>
<a class="sourceLine" id="cb8-30" data-line-number="30">        grid <span class="op">=</span> QGridLayout()</a>
<a class="sourceLine" id="cb8-31" data-line-number="31">        <span class="va">self</span>.setLayout(grid)</a>
<a class="sourceLine" id="cb8-32" data-line-number="32"></a>
<a class="sourceLine" id="cb8-33" data-line-number="33">        names <span class="op">=</span> [<span class="st">&#39;Cls&#39;</span>, <span class="st">&#39;Bck&#39;</span>, <span class="st">&#39;&#39;</span>, <span class="st">&#39;Close&#39;</span>,</a>
<a class="sourceLine" id="cb8-34" data-line-number="34">                 <span class="st">&#39;7&#39;</span>, <span class="st">&#39;8&#39;</span>, <span class="st">&#39;9&#39;</span>, <span class="st">&#39;/&#39;</span>,</a>
<a class="sourceLine" id="cb8-35" data-line-number="35">                <span class="st">&#39;4&#39;</span>, <span class="st">&#39;5&#39;</span>, <span class="st">&#39;6&#39;</span>, <span class="st">&#39;*&#39;</span>,</a>
<a class="sourceLine" id="cb8-36" data-line-number="36">                 <span class="st">&#39;1&#39;</span>, <span class="st">&#39;2&#39;</span>, <span class="st">&#39;3&#39;</span>, <span class="st">&#39;-&#39;</span>,</a>
<a class="sourceLine" id="cb8-37" data-line-number="37">                <span class="st">&#39;0&#39;</span>, <span class="st">&#39;.&#39;</span>, <span class="st">&#39;=&#39;</span>, <span class="st">&#39;+&#39;</span>]</a>
<a class="sourceLine" id="cb8-38" data-line-number="38"></a>
<a class="sourceLine" id="cb8-39" data-line-number="39">        positions <span class="op">=</span> [(i,j) <span class="cf">for</span> i <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">5</span>) <span class="cf">for</span> j <span class="kw">in</span> <span class="bu">range</span>(<span class="dv">4</span>)]</a>
<a class="sourceLine" id="cb8-40" data-line-number="40"></a>
<a class="sourceLine" id="cb8-41" data-line-number="41">        <span class="cf">for</span> position, name <span class="kw">in</span> <span class="bu">zip</span>(positions, names):</a>
<a class="sourceLine" id="cb8-42" data-line-number="42"></a>
<a class="sourceLine" id="cb8-43" data-line-number="43">            <span class="cf">if</span> name <span class="op">==</span> <span class="st">&#39;&#39;</span>:</a>
<a class="sourceLine" id="cb8-44" data-line-number="44">                <span class="cf">continue</span></a>
<a class="sourceLine" id="cb8-45" data-line-number="45">            button <span class="op">=</span> QPushButton(name)</a>
<a class="sourceLine" id="cb8-46" data-line-number="46">            grid.addWidget(button, <span class="op">*</span>position)</a>
<a class="sourceLine" id="cb8-47" data-line-number="47"></a>
<a class="sourceLine" id="cb8-48" data-line-number="48">        <span class="va">self</span>.move(<span class="dv">300</span>, <span class="dv">150</span>)</a>
<a class="sourceLine" id="cb8-49" data-line-number="49">        <span class="va">self</span>.setWindowTitle(<span class="st">&#39;Calculator&#39;</span>)</a>
<a class="sourceLine" id="cb8-50" data-line-number="50">        <span class="va">self</span>.show()</a>
<a class="sourceLine" id="cb8-51" data-line-number="51"></a>
<a class="sourceLine" id="cb8-52" data-line-number="52"></a>
<a class="sourceLine" id="cb8-53" data-line-number="53"><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</a>
<a class="sourceLine" id="cb8-54" data-line-number="54"></a>
<a class="sourceLine" id="cb8-55" data-line-number="55">    app <span class="op">=</span> QApplication(sys.argv)</a>
<a class="sourceLine" id="cb8-56" data-line-number="56">    ex <span class="op">=</span> Example()</a>
<a class="sourceLine" id="cb8-57" data-line-number="57">    sys.exit(app.exec_())</a></code></pre></div>
<p>这个例子里，我们创建了栅格化的按钮。</p>
<pre><code class="language-python">grid = QGridLayout()
self.setLayout(grid)</code></pre>
<p>创建一个QGridLayout实例，并把它放到程序窗口里。</p>
<pre><code class="language-python">names = [&#39;Cls&#39;, &#39;Bck&#39;, &#39;&#39;, &#39;Close&#39;,
        &#39;7&#39;, &#39;8&#39;, &#39;9&#39;, &#39;/&#39;,
        &#39;4&#39;, &#39;5&#39;, &#39;6&#39;, &#39;*&#39;,
        &#39;1&#39;, &#39;2&#39;, &#39;3&#39;, &#39;-&#39;,
        &#39;0&#39;, &#39;.&#39;, &#39;=&#39;, &#39;+&#39;]</code></pre>
<p>这是我们将要使用的按钮的名称。</p>
<pre><code class="language-python">positions = [(i,j) for i in range(5) for j in range(4)]</code></pre>
<p>创建按钮位置列表。</p>
<pre><code class="language-python">for position, name in zip(positions, names):

    if name == &#39;&#39;:
        continue
    button = QPushButton(name)
    grid.addWidget(button, *position)</code></pre>
<p>创建按钮，并使用<code>addWidget()</code>方法把按钮放到布局里面。</p>
<p>程序预览：</p>
<figure>
<img class="whitelist" src="docs/PyQt5/images/3-calculator.png" alt="Calculator skeleton" />
</figure>
<h2 id="制作提交反馈信息的布局">制作提交反馈信息的布局</h2>
<p>组件能跨列和跨行展示，这个例子里，我们就试试这个功能。</p>
<div class="sourceCode" id="cb13"><pre><code class="language-python"><a class="sourceLine" id="cb13-1" data-line-number="1"><span class="co">#!/usr/bin/python3</span></a>
<a class="sourceLine" id="cb13-2" data-line-number="2"><span class="co"># -*- coding: utf-8 -*-</span></a>
<a class="sourceLine" id="cb13-3" data-line-number="3"></a>
<a class="sourceLine" id="cb13-4" data-line-number="4"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb13-5" data-line-number="5"><span class="co">ZetCode PyQt5 tutorial </span></a>
<a class="sourceLine" id="cb13-6" data-line-number="6"></a>
<a class="sourceLine" id="cb13-7" data-line-number="7"><span class="co">In this example, we create a more </span></a>
<a class="sourceLine" id="cb13-8" data-line-number="8"><span class="co">complicated window layout using</span></a>
<a class="sourceLine" id="cb13-9" data-line-number="9"><span class="co">the QGridLayout manager. </span></a>
<a class="sourceLine" id="cb13-10" data-line-number="10"></a>
<a class="sourceLine" id="cb13-11" data-line-number="11"><span class="co">Author: Jan Bodnar</span></a>
<a class="sourceLine" id="cb13-12" data-line-number="12"><span class="co">Website: zetcode.com </span></a>
<a class="sourceLine" id="cb13-13" data-line-number="13"><span class="co">Last edited: August 2017</span></a>
<a class="sourceLine" id="cb13-14" data-line-number="14"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb13-15" data-line-number="15"></a>
<a class="sourceLine" id="cb13-16" data-line-number="16"><span class="im">import</span> sys</a>
<a class="sourceLine" id="cb13-17" data-line-number="17"><span class="im">from</span> PyQt5.QtWidgets <span class="im">import</span> (QWidget, QLabel, QLineEdit, </a>
<a class="sourceLine" id="cb13-18" data-line-number="18">    QTextEdit, QGridLayout, QApplication)</a>
<a class="sourceLine" id="cb13-19" data-line-number="19"></a>
<a class="sourceLine" id="cb13-20" data-line-number="20"><span class="kw">class</span> Example(QWidget):</a>
<a class="sourceLine" id="cb13-21" data-line-number="21"></a>
<a class="sourceLine" id="cb13-22" data-line-number="22">    <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>):</a>
<a class="sourceLine" id="cb13-23" data-line-number="23">        <span class="bu">super</span>().<span class="fu">__init__</span>()</a>
<a class="sourceLine" id="cb13-24" data-line-number="24"></a>
<a class="sourceLine" id="cb13-25" data-line-number="25">        <span class="va">self</span>.initUI()</a>
<a class="sourceLine" id="cb13-26" data-line-number="26"></a>
<a class="sourceLine" id="cb13-27" data-line-number="27"></a>
<a class="sourceLine" id="cb13-28" data-line-number="28">    <span class="kw">def</span> initUI(<span class="va">self</span>):</a>
<a class="sourceLine" id="cb13-29" data-line-number="29"></a>
<a class="sourceLine" id="cb13-30" data-line-number="30">        title <span class="op">=</span> QLabel(<span class="st">&#39;Title&#39;</span>)</a>
<a class="sourceLine" id="cb13-31" data-line-number="31">        author <span class="op">=</span> QLabel(<span class="st">&#39;Author&#39;</span>)</a>
<a class="sourceLine" id="cb13-32" data-line-number="32">        review <span class="op">=</span> QLabel(<span class="st">&#39;Review&#39;</span>)</a>
<a class="sourceLine" id="cb13-33" data-line-number="33"></a>
<a class="sourceLine" id="cb13-34" data-line-number="34">        titleEdit <span class="op">=</span> QLineEdit()</a>
<a class="sourceLine" id="cb13-35" data-line-number="35">        authorEdit <span class="op">=</span> QLineEdit()</a>
<a class="sourceLine" id="cb13-36" data-line-number="36">        reviewEdit <span class="op">=</span> QTextEdit()</a>
<a class="sourceLine" id="cb13-37" data-line-number="37"></a>
<a class="sourceLine" id="cb13-38" data-line-number="38">        grid <span class="op">=</span> QGridLayout()</a>
<a class="sourceLine" id="cb13-39" data-line-number="39">        grid.setSpacing(<span class="dv">10</span>)</a>
<a class="sourceLine" id="cb13-40" data-line-number="40"></a>
<a class="sourceLine" id="cb13-41" data-line-number="41">        grid.addWidget(title, <span class="dv">1</span>, <span class="dv">0</span>)</a>
<a class="sourceLine" id="cb13-42" data-line-number="42">        grid.addWidget(titleEdit, <span class="dv">1</span>, <span class="dv">1</span>)</a>
<a class="sourceLine" id="cb13-43" data-line-number="43"></a>
<a class="sourceLine" id="cb13-44" data-line-number="44">        grid.addWidget(author, <span class="dv">2</span>, <span class="dv">0</span>)</a>
<a class="sourceLine" id="cb13-45" data-line-number="45">        grid.addWidget(authorEdit, <span class="dv">2</span>, <span class="dv">1</span>)</a>
<a class="sourceLine" id="cb13-46" data-line-number="46"></a>
<a class="sourceLine" id="cb13-47" data-line-number="47">        grid.addWidget(review, <span class="dv">3</span>, <span class="dv">0</span>)</a>
<a class="sourceLine" id="cb13-48" data-line-number="48">        grid.addWidget(reviewEdit, <span class="dv">3</span>, <span class="dv">1</span>, <span class="dv">5</span>, <span class="dv">1</span>)</a>
<a class="sourceLine" id="cb13-49" data-line-number="49"></a>
<a class="sourceLine" id="cb13-50" data-line-number="50">        <span class="va">self</span>.setLayout(grid) </a>
<a class="sourceLine" id="cb13-51" data-line-number="51"></a>
<a class="sourceLine" id="cb13-52" data-line-number="52">        <span class="va">self</span>.setGeometry(<span class="dv">300</span>, <span class="dv">300</span>, <span class="dv">350</span>, <span class="dv">300</span>)</a>
<a class="sourceLine" id="cb13-53" data-line-number="53">        <span class="va">self</span>.setWindowTitle(<span class="st">&#39;Review&#39;</span>)    </a>
<a class="sourceLine" id="cb13-54" data-line-number="54">        <span class="va">self</span>.show()</a>
<a class="sourceLine" id="cb13-55" data-line-number="55"></a>
<a class="sourceLine" id="cb13-56" data-line-number="56"></a>
<a class="sourceLine" id="cb13-57" data-line-number="57"><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</a>
<a class="sourceLine" id="cb13-58" data-line-number="58"></a>
<a class="sourceLine" id="cb13-59" data-line-number="59">    app <span class="op">=</span> QApplication(sys.argv)</a>
<a class="sourceLine" id="cb13-60" data-line-number="60">    ex <span class="op">=</span> Example()</a>
<a class="sourceLine" id="cb13-61" data-line-number="61">    sys.exit(app.exec_())</a></code></pre></div>
<p>我们创建了一个有三个标签的窗口。两个行编辑和一个文版编辑，这是用<code>QGridLayout</code>模块搞定的。</p>
<pre><code class="language-python">grid = QGridLayout()
grid.setSpacing(10)</code></pre>
<p>创建标签之间的空间。</p>
<pre><code class="language-python">grid.addWidget(reviewEdit, 3, 1, 5, 1)</code></pre>
<p>我们可以指定组件的跨行和跨列的大小。这里我们指定这个元素跨5行显示。</p>
<p>程序预览：</p>
<figure>
<img class="whitelist" src="docs/PyQt5/images/3-review.png" alt="review example" />
</figure>
